require 'rake'
require 'rake/tasklib'
require File.dirname(__FILE__) + '/../facades'

module Rubicant::Tasks

  class MbUnitTask < Rake::TaskLib
    attr_reader :name
    attr_accessor :mbunit_dir, :test_dir, :test_files, :assembly_path
    attr_accessor :report_folder, :report_name_format, :report_type
    attr_accessor :show_reports, :transform, :filter_category
    attr_accessor :exclude_category, :filter_author, :filter_type
    attr_accessor :filter_namespace, :verbose, :shadow_copy

    def initialize(name)
      @name = name
      yield self if block_given?
      define
    end

    def define
      fail ('mbunit_dir must be set') if (@mbunit_dir.nil?)
      fail ('test_dir must be set') if (@test_dir.nil?)
      fail ('test_files must be set') if (@test_files.nil?)

      @mbunit_dir = "./" if @mbunit_dir.length == 0
      @mbunit_dir = File.expand_path(@mbunit_dir)

      exec_opts = {}
      exec_opts.merge!({:working_dir => test_dir})

      exec_args = []
      exec_args << "/ap:#{@assembly_path.to_a.join(' /ap:')}" unless @assembly_path.nil?
      exec_args << "/rf:#{@report_folder}" unless @report_folder.nil?
      exec_args << "/rnf:#{@report_name_format}" unless @report_name_format.nil?
      exec_args << "/rt:#{@report_type}" unless @report_type.nil?
      exec_args << "/sr#{@show_reports}" unless @show_reports.nil?
      exec_args << "/tr:#{@transform}" unless @transform.nil?
      exec_args << "/fc:#{@filter_category}" unless @filter_category.nil?
      exec_args << "/ec:#{@exclude_category}" unless @exclude_category.nil?
      exec_args << "/fa:#{@filter_author}" unless @filter_author.nil?
      exec_args << "/ft:#{@filter_type}" unless @filter_type.nil?
      exec_args << "/fn:#{@filter_namespace}" unless @filter_namespace.nil?
      exec_args << "/v#{@verbose}" unless @verbose.nil?
      exec_args << "/sc#{@shadow_copy}" unless @shadow_copy.nil?
      exec_args << @test_files.to_a.join(' ')
      exec_opts.merge!({:args => exec_args})

      task name do
        copy_mbunit_files(@mbunit_dir, @test_dir)
        Rubicant::Runner.exec("MbUnit.Cons.exe", exec_opts)
        remove_mbunit_files(test_dir)
      end
      self
    end
    private
    def copy_mbunit_files(mbunit_dir, test_dir)
      required_mbunit_files.each do |file|
        Rubicant::Files.copy("#{mbunit_dir}/#{file}", test_dir)
      end
    end

    def remove_mbunit_files(test_dir)
      required_mbunit_files.each do |file|
        begin
          Rubicant::Files.remove("#{test_dir}/#{file}")
        rescue
          #sometimes the mbunit files are still in use for some reason
          sleep 1
          Rubicant::Files.remove("#{test_dir}/#{file}")
        end
      end
    end
    def required_mbunit_files()
      return ["QuickGraph.dll", "QuickGraph.Algorithms.dll", "MbUnit.Framework.dll", "MbUnit.Cons.exe", "MbUnit.Cons.exe.config"]
    end

  end
end